# Генерация исключений и оператор raise


Иногда возникает необходимость вручную сгенерировать то или иное исключение. Для этого применяется оператор raise. Например, сгенерируем исключение

```python
try:
    age = int(input("Введите возраст: "))
    if age > 110 or age < 1:
        raise Exception("Некорректный возраст")
    print("Ваш возраст:", age)
except ValueError:
    print("Введены некорректные данные")
except Exception as e:
    print(e)
print("Завершение программы")
```

Оператору raise передается объект BaseException - в данном случае объект Exception. 

В конструктор этого типа можно ему передать сообщение, которое затем можно вывести пользователю. 

В итоге, если age будет больше 110 или меньше 1, то сработает оператор raise, который сгенерирует исключение. 

В итоге управление программой перейдет к блоку except, который обрабатывает исключения типа Exception:

```
Введите возраст: 100500
Некорректный возраст
Завершение программы
```


# Создание своих типов исключений

В языке Python мы не ограничены только встроенными типами исключений и можем, применяя наследование, при необходимости создавать свои типы исключений. 

Например, возьмем следующий класс Person:

```python
class Person:
    def __init__(self, name, age):
        self.__name = name  # устанавливаем имя
        self.__age = age   # устанавливаем возраст
 
    def display_info(self):
        print(f"Имя: {self.__name}  Возраст: {self.__age}")

```

Здесь класс Person в конструкторе получает значения для имени и возраста и присваивает их приватным переменным name и age. 

Однако при создании объекта Person мы можем передать в конструктор некорректное с точки зрения логики значение - например, отрицательное число. 

Одним из способов решения данной ситуации представляет генерация исключения при передаче некорректных значений.

Итак, определим следующий код программы:


```python
class PersonAgeException(Exception):
    def __init__(self, age, minage, maxage):
        self.age = age
        self.minage = minage
        self.maxage = maxage
 
    def __str__(self):
        return f"Недопустимое значение: {self.age}. " \
               f"Возраст должен быть в диапазоне от {self.minage} до {self.maxage}"
 
 
class Person:
    def __init__(self, name, age):
        self.__name = name  # устанавливаем имя
        minage, maxage = 1, 110
        if minage < age < maxage:   # устанавливаем возраст, если передано корректное значение
            self.__age = age
        else:                       # иначе генерируем исключение
            raise PersonAgeException(age, minage, maxage)
 
    def display_info(self):
        print(f"Имя: {self.__name}  Возраст: {self.__age}")
 
try:
    tom = Person("Tom", 37)
    tom.display_info()  # Имя: Tom  Возраст: 37
 
    bob = Person("Bob", -23)
    bob.display_info()
except PersonAgeException as e:
    print(e)    # Недопустимое значение: -23. Возраст должен быть в диапазоне от 1 до 110

```

В начале здесь определен класс `PersonAgeException`, который наследуется от класса `Exception`. 

Как правило, собственные классы исключений наследуются от класса `Exception`. 

Класс `PersonAgeException` предназначен для исключений, связанных с возрастом пользователя.

В конструкторе `PersonAgeException` получаем три значения - собственное некорректное значение, которое послужило причиной исключения, а также минимальное и максимальное значения возраста.

```python
class PersonAgeException(Exception):
    def __init__(self, age, minage, maxage):
        self.age = age
        self.minage = minage
        self.maxage = maxage
 
    def __str__(self):
        return f"Недопустимое значение: {self.age}. " \
               f"Возраст должен быть в диапазоне от {self.minage} до {self.maxage}"

```

В функции `__str__` определяем текстовое представление класса - по сути сообщение об ошибке.

В конструкторе класса Persoon проверяем переданное для возраста пользователя значение. 

И если это значение не соответствует определенному диапазону, то генерируем исключение типа `PersonAgeException`:

```python
raise PersonAgeException(age, minage, maxage)
```

При применении класса `Person` нам следует учитывать, что конструктор класса может сгенерировать исключение при передаче некорректного значения. 

Поэтому создание объектов Person обертывается в конструкцию `try..except`:


```python
try:
    tom = Person("Tom", 37)
    tom.display_info()  # Имя: Tom  Возраст: 37
 
    bob = Person("Bob", -23)  # генерируется исключение типа PersonAgeException
    bob.display_info()
except PersonAgeException as e:
    print(e)    # Недопустимое значение: -23. Возраст должен быть в диапазоне от 1 до 110
```

И если при вызове конструктора Person будет сгенерировано исключение типа `PersonAgeException`, то управление программой перейдет к блоку `except`, который обрабатывает исключения типа `PersonAgeException` в виде вывода информации об исключении на консоль.